// ListView.cpp: implementation of the ListView class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ListView.h"
#include "ListViewPeer.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//IMPLEMENT_DYNAMIC(ListView, AWTComponent)

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ListView::ListView()
{
	m_itemListener = NULL;
	m_sel = -1;
}

ListView::~ListView()
{
	while (m_items.GetCount() > 0)
		delete m_items.RemoveTail();
	while (m_columns.GetCount() > 0)
		delete m_columns.RemoveTail();

	if (m_itemListener != NULL)
	{
		if (m_itemListener->isMultiCaster())
		{
#ifdef UNDER_CE
			AWTEventMulticaster* mc = (AWTEventMulticaster*)m_itemListener;
#else
			AWTEventMulticaster* mc = dynamic_cast<AWTEventMulticaster*>(m_itemListener);
#endif
			delete mc;
		}
	}
}

CWnd* ListView::createComponent()
{
	CWnd* wParent = getParent()->getPeer();
	if (wParent == NULL)
		return wParent;
	ListViewPeer* pwnd = new ListViewPeer(this);
	CWnd* wndParent = getParent()->getPeer();
	if (wndParent == NULL)
		return NULL;

	pwnd->Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL, getBounds(), wndParent, 100);

	pwnd->SetExtendedStyle(LVS_EX_FULLROWSELECT);

	POSITION pos = m_columns.GetHeadPosition();
	int n = 0;
	while(pos != NULL)
	{
		ListViewColumn* col = (ListViewColumn*)m_columns.GetNext(pos);
		pwnd->InsertColumn(n, col->getLabel(), LVCFMT_LEFT, col->getWidth(), n);
		n++;
	}

/*
	pwnd->InsertColumn(0, "Column 1", LVCFMT_LEFT, 150, 0);
	pwnd->InsertColumn(1, "Column 2", LVCFMT_LEFT, 150, 1);
	pwnd->InsertColumn(2, "Column 3", LVCFMT_LEFT, 150, 2);
	pwnd->InsertColumn(3, "Column 4", LVCFMT_LEFT, 150, 3);
	pwnd->InsertColumn(4, "Column 5", LVCFMT_LEFT, 150, 4);
	pwnd->InsertColumn(5, "Column 6", LVCFMT_LEFT, 150, 5);
*/
	LV_ITEM lvi = {0};

	int r = 0;
	pos = m_items.GetHeadPosition();
	while (pos != NULL)
	{
		ListViewItem* i = (ListViewItem*)m_items.GetNext(pos);

		lvi.mask = LVIF_TEXT;
		lvi.iItem = r;
		lvi.iSubItem = 0;
		lvi.pszText = i->getLabel();
		pwnd->InsertItem(&lvi);

//		if (i->getTag() != 0)
//		{
//			pwnd->SetItemData(r, i->getTag());
//		}

		pwnd->SetItemData(r, (DWORD)i);

		CObList* pSubItems = i->getSubItems();
		POSITION p2 = pSubItems->GetHeadPosition();
		int c = 1;
		while (p2 != NULL)
		{
			ListViewSubItem* i = (ListViewSubItem*)pSubItems->GetNext(p2);
			lvi.iItem = r;
			lvi.iSubItem = c++;
			lvi.pszText = i->getLabel();
			pwnd->SetItem(&lvi);
		}
		r++;
	}

	if (m_sel != -1)
	{
		lvi.iItem = m_sel;
		lvi.mask = LVIF_STATE;
		lvi.state = LVIS_SELECTED;
		lvi.stateMask = LVIS_SELECTED;
		pwnd->SetItem(&lvi);
		pwnd->EnsureVisible(m_sel, FALSE);
		CString s;
		AWTItemEvent ev(this, m_sel, pwnd->GetItemData(m_sel), AWTItemEvent::SELECTED);
		processItemEvent(&ev);
	}

	return pwnd;
}

CSize ListView::getMinimumSize()
{
	return getPreferredSize();
}

CSize ListView::getPreferredSize()
{
	if (m_peer == NULL)
		return CSize(0,0);
	return CSize(10,10);
}

void ListView::addColumn(LPSTR s, int w)
{
	m_columns.AddTail(new ListViewColumn(s, w));
}

void ListView::processItemEvent(AWTItemEvent* e)
{
  if (m_itemListener != NULL) 
		m_itemListener->itemStateChanged(e);
}

void ListView::clear()
{
	while (m_items.GetCount() > 0)
		delete m_items.RemoveTail();

	if (m_peer != NULL)
	{
		((ListViewPeer*)m_peer)->DeleteAllItems();
	}	
}

void ListView::setColumnWidth(int nCol, int w)
{
	POSITION pos = m_columns.FindIndex(nCol);
	if (pos != NULL)
	{
		ListViewColumn* col = (ListViewColumn*)m_columns.GetAt(pos);
		col->setWidth(w);
		if (m_peer != NULL)
		{
			((ListViewPeer*)m_peer)->SetColumnWidth(nCol, w);
		}		
		return;
	}
}

ListViewItem* ListView::addItem(CString& s, DWORD tag)
{
	ListViewItem* i = new ListViewItem(s, tag);
	m_items.AddTail(i);

	if (m_peer != NULL)
	{
		ListViewPeer* pwnd = (ListViewPeer*)m_peer;
		LV_ITEM lvi = {0};
		lvi.mask = LVIF_TEXT;
		lvi.iItem = m_items.GetCount()-1;
		lvi.iSubItem = 0;
		lvi.pszText = i->getLabel();
		pwnd->InsertItem(&lvi);
		pwnd->SetItemData(lvi.iItem, (DWORD)i);
	}
	
	return i;
}

void ListView::select(int index)
{
	if (index < 0)
		return;
	m_sel = index;	
	LV_ITEM lvi = {0};
	if (m_peer != NULL)
	{
		ListViewPeer* pwnd = (ListViewPeer*)m_peer;
//		DWORD dwData = pwnd->GetItemData(m_sel); 
		lvi.iItem = m_sel;
		lvi.mask = LVIF_STATE;
		lvi.state = LVIS_SELECTED;
		lvi.stateMask = LVIS_SELECTED;
		pwnd->SetItem(&lvi);
//		pwnd->SetItemData(lvi.iItem, dwData);
		pwnd->EnsureVisible(m_sel, FALSE);
		CString s;
		AWTItemEvent ev(this, m_sel, pwnd->GetItemData(m_sel), AWTItemEvent::SELECTED);
		processItemEvent(&ev);
	}
}

void ListView::removeItem(int index)
{
	if ((index >= 0) && (index < m_items.GetCount()))
	{
		POSITION pos = m_items.FindIndex(index);
		ListViewItem* i = (ListViewItem*)m_items.GetAt(pos);
		delete i;
		m_items.RemoveAt(pos);
		if (m_peer != NULL)
		{
			ListViewPeer* pwnd = (ListViewPeer*)m_peer;
			pwnd->DeleteItem(index);		
		}
	}
}

void ListView::columnClicked(int col)
{
	ListViewPeer* pwnd = (ListViewPeer*)m_peer;
	if (col == m_sortColumn)
	{
		//reverse order
		m_sortOrder = !m_sortOrder;
	}
	else
	{
		m_sortColumn = col;
	}
	m_sortParms.nCol = col;
	m_sortParms.nOrder = m_sortOrder;
	m_sortParms.pThis = this;
	pwnd->SortItems(CompareFunc, (DWORD)&m_sortParms);	
}

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	SORTPARMS* pParms = (SORTPARMS*)lParamSort;
	ListView* plv = (ListView*)pParms->pThis;

	ListViewItem* plvi1 = (ListViewItem*)lParam1;
	ListViewItem* plvi2 = (ListViewItem*)lParam2;

	CString str1;
	CString str2;

	if (pParms->nCol == 0)
	{
		str1 = plvi1->getLabel();
		str2 = plvi2->getLabel();
	}
	else
	{
		CObList* pList = plvi1->getSubItems();
		POSITION pos = pList->FindIndex(pParms->nCol-1);
		str1 = ((ListViewSubItem*)pList->GetAt(pos))->getLabel();
		pList = plvi2->getSubItems();
		pos = pList->FindIndex(pParms->nCol-1);
		str2 = ((ListViewSubItem*)pList->GetAt(pos))->getLabel();
	}

	if (pParms->nOrder)
		return str1.Compare(str2.GetBuffer(0));
	else
		return str2.Compare(str1.GetBuffer(0));
}

